﻿using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using System.Collections.Concurrent;

namespace HHFileViewServer
{
    public static class ServerOp
    {
        /// <summary>
        /// 项目根目录
        /// </summary>
        public static string RootPath { get; set; } = string.Empty;

        /// <summary>
        /// 服务配置
        /// </summary>
        public static ServerConfig ServerConfig { get; set; }

        /// <summary>
        /// 获取服务
        /// </summary>
        /// <typeparam name="T1"></typeparam>
        /// <typeparam name="T2"></typeparam>
        /// <returns></returns>
        /// <exception cref="NullReferenceException"></exception>
        public static T1 GetService<T1, T2>(this IServiceProvider serviceProvider)
        {
            var service = serviceProvider.GetServices<T1>().FirstOrDefault(x => x.GetType() == typeof(T2));
            if (service == null)
                throw new NullReferenceException();
            return service;
        }
    }

    public class ServerConfig
    {
        /// <summary>
        /// 下载文件存放地址
        /// </summary>
        public string DownloadPath { get; set; }
        /// <summary>
        /// LibreOffice安装目录
        /// </summary>
        public string LibreOffice { get; set; }
        /// <summary>
        /// 文件大小上限
        /// </summary>
        public int SizeLimit { get; set; }
        /// <summary>
        /// 是否显示标题头
        /// </summary>
        public bool ShowNav { get; set; }
        /// <summary>
        /// 文件清理配置
        /// </summary>
        public ClearConfig ClearConfig { get; set; }
    }

    /// <summary>
    /// 文件清理配置
    /// </summary>
    public class ClearConfig
    {
        /// <summary>
        /// 是否自动清理
        /// </summary>
        public bool AutoClear { get; set; }
        /// <summary>
        /// 文件保留时间
        /// </summary>
        public int RetentionTime { get; set; }
        /// <summary>
        /// 任务执行间隔
        /// </summary>
        public int TaskInterval { get; set; }
    }

    public class ConfigHelper
    {
        /// <summary>
        /// 缓存数据（配置信息）
        /// </summary>
        private static readonly ConcurrentDictionary<string, object> _setting =
           new ConcurrentDictionary<string, object>();
        private static IConfiguration configuration;

        /// <summary>
        /// 获取配置信息
        /// </summary>
        /// <typeparam name="T">数据类型</typeparam>
        /// <param name="key">键</param>
        /// <returns></returns>
        public static T GetAppSettings<T>(string key) where T : class, new()
        {
            if (configuration == null)
            {
                string fileName = "appsettings.json";
                if (GetValue<string>("env") == "dev")
                {
                    fileName = "appsettings.Development.json";
                }

                var filePath = $"{ServerOp.RootPath}/{fileName}";

                if (File.Exists(filePath))
                {
                    var builder = new ConfigurationBuilder();
                    builder.AddJsonFile(filePath, false, true);
                    configuration = builder.Build();
                }
            }

            if (configuration == null)
            {
                return new T();
            }

            var appconfig = new ServiceCollection()
                .AddOptions()
                .Configure<T>(configuration.GetSection(key))
                .BuildServiceProvider()
                .GetService<IOptions<T>>()
                .Value;

            return appconfig;
        }

        /// <summary>
        /// 获取数据值
        /// </summary>
        /// <typeparam name="T">类型</typeparam>
        /// <param name="key">键值</param>
        /// <returns></returns>
        public static T GetValue<T>(string key) where T : class
        {
            _setting.TryGetValue(key, out object result);
            return result as T;
        }

        /// <summary>
        /// 获取配置信息
        /// </summary>
        /// <returns></returns>
        public static ServerConfig GetConfig()
        {
            return GetAppSettings<ServerConfig>("ServerConfig");

        }
    }
}
